/**
 * Copyright @2019 Josin All Rights Reserved.
 * Author: Josin
 * Email : xeapplee@gmail.com
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <fc_string.h>
#include <limits.h>

inline
char *
e_substr(char *src, unsigned long len)
{
/**
 * @brief This function will automatically add '\0' at the end of the string
 */
    if (!src) return NULL;
    char *res;
    res = malloc( sizeof(char) * (len + 1) );
    if ( !res ) return NULL;
    e_memzero(res, sizeof(char) * (len + 1));
    e_copymem(res, src, sizeof(char) * len);
    return res;
}

long
e_concat_str(char **dest, char *src, unsigned long len, int _reset)
{
/**
 * @brief This function's first parameter must be NULL when first time invoking
 * After then e_concat_str will automatically append after the previous invoking result.
 */
    char       *t;
    static long al = 0;
    if(_reset)  al = 0;
    
    t = realloc(*dest, sizeof(char) * (al + len));
    if(!t)
    {
        e_memfree(dest);
        return al;
    }
    e_copymem(t + al, src, sizeof(char) * len);
   *dest = t;
    al  += len;
    return al;
}

CSTRING *
new_cstring()
{
    CSTRING *ptr = malloc( sizeof(CSTRING) );
    if (!ptr) {
        return NULL;
    }
    e_memzero(ptr, sizeof(CSTRING));
    return ptr;
}

void
new_cstring_free(CSTRING *c)
{
    if(!c) return;
    e_memfree(c->s);
    e_memfree(c);
}

int
new_cstring_add_long_long(CSTRING *c, long long i)
{
    char            *t;
    char            buff[20];
    unsigned long   sl;
    if(!c) {
       return FALSE;
    }
    e_memzero(buff, sizeof(buff));
    sprintf(buff, "%lld", i);
    
    if (c->t - c->l > sizeof(buff)) {
        e_copymem(c->s + c->l, buff, sizeof(char) * sizeof(buff));
        c->l += strlen(buff);
    } else {
        if ( BUFFER_SIZE > sizeof(buff) )
        {
            sl = c->l + BUFFER_SIZE;
        }
        t = malloc( sizeof(char) * sl );
        e_memzero(t, sizeof(char) * sl );
        e_copymem(t, c->s, sizeof(char) * (c->l));
        e_copymem(t + c->l, buff, sizeof(buff) * sizeof(char));
        e_memfree(c->s);
        c->s = t;
        c->t = sl;
        c->l += sizeof(buff);
    }
    return TRUE;
}

int
new_cstring_add_double(CSTRING *c, double d)
{
    char            *t;
    char            buff[100];
    unsigned long   sl;
    if(!c) {
        return FALSE;
    }
    e_memzero(buff, sizeof(buff));
    sprintf(buff, "%f", d);
    
    if (c->t - c->l > sizeof(buff)) {
        e_copymem(c->s + c->l, buff, sizeof(char) * sizeof(buff));
        c->l += strlen(buff);
    } else {
        if ( BUFFER_SIZE > sizeof(buff) )
        {
            sl = c->l + BUFFER_SIZE;
        }
        t = malloc( sizeof(char) * sl );
        e_memzero(t, sizeof(char) * sl );
        e_copymem(t, c->s, sizeof(char) * (c->l));
        e_copymem(t + c->l, buff, sizeof(char) * sizeof(buff));
        e_memfree(c->s);
        c->s = t;
        c->l+= sizeof(buff);
        c->t = sl;
    }
    return TRUE;
}

int
new_cstring_add_string(CSTRING *c, char *s, long l)
{
    char            *t;
    unsigned long   sl;
    if(!c) {
        return FALSE;
    }
    
    if (c->t - c->l > l) {
        e_copymem(c->s + c->l, s, sizeof(char) * l);
        c->l+= l;
    } else {
        if ( BUFFER_SIZE > l )
        {
            sl = c->l + BUFFER_SIZE;
        }
        else
        {
            sl = c->l + l + 1;
        }
        t = malloc( sizeof(char) * sl );
        e_memzero(t, sizeof(char) * sl );
        e_copymem(t, c->s, sizeof(char) * (c->l));
        e_copymem(t + c->l, s, sizeof(char) * l);
        e_memfree(c->s);
        c->s = t;
        c->l+= l;
        c->t = sl;
    }
    return TRUE;
}

int
new_cstring_add_char(CSTRING *c, char v)
{
    char            *t;
    unsigned long   sl;
    if( !c ) {
        return FALSE;
    }
    
    if (c->t - c->l > sizeof(char) ) {
        e_copymem(c->s + c->l, &v, sizeof(char) * sizeof(v));
        c->l += sizeof(v);
    } else {
        if ( BUFFER_SIZE > sizeof(v) )
        {
            sl = c->l + BUFFER_SIZE;
        }
        t = malloc( sizeof(char) * sl );
        e_memzero(t, sizeof(char) * sl );
        e_copymem(t, c->s, sizeof(char) * (c->l));
        e_copymem(t + c->l, &v, sizeof(char));
        e_memfree(c->s);
        c->s = t;
        c->t+= sl;
        c->l+= sizeof(v);
    }
    return TRUE;
}

int
new_cstring_0(CSTRING *c)
{
    char    *tv;
    if ( !c || !c->s ) {
        return FALSE;
    }
    
    if ( c->l + 1 > c->t) {
        tv = malloc( sizeof(char) * ( c->l + 1 ));
        e_memzero(tv, sizeof(char) * (c->l + 1));
        e_copymem(tv, c->s, c->l * sizeof(char));
        e_copymem(tv + c->l, "\0", sizeof(char));
    }
    else
    {
        e_copymem(c->s + c->l, "\0", sizeof(char));
    }
    return TRUE;
}